#pragma once
#include "Runtime/CGI/CGIPrefix.h"
#include "CGIVulkanQueue.h"
namespace Alice{
    class CGIVulkanCommandListContextImmediate;
    class FenceManager;
    struct FPixelFormatInfo;
    enum class EPixelFormatCapabilities : uint32;
    class VulkanPhysicalDeviceFeatures
    {
    public:
        void Query(VkPhysicalDevice PhysicalDevice, uint32 APIVersion);
        VkPhysicalDeviceFeatures	     Core_1_0;
        VkPhysicalDeviceVulkan11Features Core_1_1;
        VkPhysicalDeviceVulkan12Features Core_1_2;
        VkPhysicalDeviceVulkan13Features Core_1_3;
    };
    class CGIVulkanDevice{
    public:
        VkDevice mDevice;
        VkPhysicalDevice mVkPhysicalDevice;
        uint32 mAPIVersion;
        VkPhysicalDeviceProperties mVkPhysicalDeviceProperties;
        VkPhysicalDeviceIDPropertiesKHR mVkPhysicalDeviceIDProperties;
        VkPhysicalDeviceSubgroupProperties mVkPhysicalDeviceSubgroupProperties;
        std::vector<VkQueueFamilyProperties> mVkQueueFamilyProperties;
        VulkanPhysicalDeviceFeatures mVulkanPhysicalDeviceFeatures;

        CGIVulkanQueue * mGraphicsQueue;
        CGIVulkanQueue * mComputeQueue;
        CGIVulkanQueue * mTransferQueue;
        CGIVulkanQueue * mPresentQueue;
        
        CGIVulkanCommandListContextImmediate*mImmediateContext;
        VkFormatProperties mFormatProperties[VK_FORMAT_RANGE_SIZE];
        VkComponentMapping PixelFormatComponentMapping[EPixelFormat::PF_NUM];
        mutable std::unordered_map<VkFormat, VkFormatProperties> mExtensionFormatProperties;
        FenceManager*mFenceManager;
        CGIVulkanDevice(VkPhysicalDevice inGPU,uint32 inAPIVersion);
        void InitGPU();
        void InitDevice();
        void SetupPresentQueue(VkSurfaceKHR inSurface);
        CGIVulkanQueue * GetPresentQueue()const
        {
            return mPresentQueue;
        }
        inline VkPhysicalDevice GetPhysicalHandle() const
        {
            return mVkPhysicalDevice;
        }
        inline VkDevice GetDevice() const
        {
            return mDevice;
        }
        CGIVulkanCommandListContextImmediate& GetImmediateContext()
        {
            return *mImmediateContext;
        }
        inline FenceManager& GetFenceManager()
        {
            return *mFenceManager;
        }
        void SetupFormats();
        void MapBufferFormatSupport(FPixelFormatInfo& PixelFormatInfo, EPixelFormat UEFormat, VkFormat VulkanFormat);
        const VkFormatProperties& GetFormatProperties(VkFormat InFormat) const;
        void MapImageFormatSupport(FPixelFormatInfo& PixelFormatInfo, const std::vector<VkFormat>& PrioritizedFormats, EPixelFormatCapabilities RequiredCapabilities);
        void MapFormatSupport(EPixelFormat UEFormat, std::initializer_list<VkFormat> PrioritizedFormats, const VkComponentMapping& ComponentMapping, EPixelFormatCapabilities RequiredCapabilities, int32 BlockBytes);
        void MapFormatSupport(EPixelFormat UEFormat, std::initializer_list<VkFormat> PrioritizedFormats, const VkComponentMapping& ComponentMapping);
        void MapFormatSupport(EPixelFormat UEFormat, std::initializer_list<VkFormat> PrioritizedFormats, const VkComponentMapping& ComponentMapping, int32 BlockBytes);
        void MapFormatSupport(EPixelFormat UEFormat, std::initializer_list<VkFormat> PrioritizedFormats, const VkComponentMapping& ComponentMapping, EPixelFormatCapabilities RequiredCapabilities);
    };
}